#!/bin/bash
# USAGE: reverse_ssh_tunnel [-i] Where -i kicks off the node installation scripts
##############################
# NOTES: 1. ssh server must be running on each host
#        2. autossh must be installed on each host
#        3. "hostname -s" must resolve to a machine name in the case statement
#	     4. when running as root (at startup) ensure the path to the config file exist. I suggest sym-linking to /etc 
#        5. I suggest running fail2ban and only allowing ssh key access on each client
#        6. I use dropbox to sync the config file changes to all nodes.
##############################
# TODO: find the machines MAC address and insert it properly to the config file
##############################
# check all required binaries are installed
##############################
DEPENDS=( autossh )
MIDDLEMAN_SERVER_AND_USERNAME=""
AUTOSSH_PORT=22074
AUTOSSH_GATETIME=0
config_file="/etc/reverse_ssh.conf"
email_address=""

command_exists () 
{
    type -P "$1" &> /dev/null ;
}


process_depends()
{
for i in "${DEPENDS[@]}"
do
    command_exists $i
        if [ $? -ne "0" ]; then
	    echo "$i does not exist.. please install"
    	    #exit 1
        fi
done
}

process_args()
{
install="n"; email="n"; assume="n"
for ARG in "$@"
      do
       case $ARG in
            "-i" ) install="y";;
            "-e" ) email="y";;
            "-y" ) assume="y";;
       esac
       echo $ARG
done
echo "install = $install email = $email assume = $assume"
}

# Call process_args to see what we need to do
clear
process_args "$@"

##############################
# Automated installation process with "-i" switch
##############################
if [ "$install" = "y" ]; then
    echo -e "Reverse_ssh_tunnel client installation process\n"
    ### Check if config file is symlinked to /etc
    if [ -e $config_file ]; then
        echo "Looks like $config_file is already setup in /etc.. SKIPPING"
    elif [ "$assume" != "y" ]; then
            echo -n "Would you like to symlink the config file to /etc <y/n> "
            read opt
        fi

        if [ "$opt" = "y" -o "$assume" = "y" ]; then

## Check for reverse_ssh.conf in current directory and if it exists use it.
            if [ -e "$(pwd)/reverse_ssh.conf" ]; then
                echo "Using conf file in current directory OK"
                orig_conf="$(pwd)/reverse_ssh.conf"
            else
                echo -n "Config not in current directory Please enter the location of the config file: "
                read orig_conf
            fi
            if [ -e "$orig_conf" ]; then 
                sudo ln -s $orig_conf /etc/reverse_ssh.conf
            else
                echo "Could not find the config file.. MANUALLY"
            fi
    fi

### Try to find the network manager to create post connect hooks
### First lets see if wicd is installed
    nm_found="0"
    command_exists wicd-client
    if [ $? -ne "0" ]; then
        echo "Checking for wicd installation.. NO"
    else
        echo "Checking for wicd installation.. YES"
        nm_found="1"
        if [ $nm_found -eq "1" ] && [ ! -e "/etc/wicd/scripts/postconnect/reverse_ssh_tunnel" ]; then
            if [ "$assume" != "y" ]; then 
                echo -n "Would you like to copy $0 to /etc/wicd/scripts/postconnect <y/n> "
                read opt
            fi
            if [ "$opt" = "y" ] || [ "$assume" = "y"]; then
                sudo cp $0 /etc/wicd/scripts/postconnect/
            else
                echo "No file copied. User performing MANUALLY"
            fi
	else
		echo "wicd postconnect Sym-link already exists.. SKIPPING"
        fi
    fi

### Next lets see if /etc/network/if-up.d/ exists. 
### This is the standard on debian/ubuntu/linux mint installations
    if [ "$nm_found" -ne "1" ]; then
        if [ -d "/etc/network/if-up.d/" ]; then
	    nm_found="1"
            echo "Checking for network manager installation.. Yes"
	    echo "Checking for reverse_ssh_tunnel sym-link"
            if [ $nm_found -eq "1" ] && [ ! -e "/etc/network/if-up.d/reverse_ssh_tunnel" ]; then
                if [ "$assume" != "y" ]; then
                    echo -n "Would you like to copy $0 to /etc/network/if-up.d <y/n> "
                    read opt
                fi
                if [ "$opt" = "y" ] || [ "$assume" = "y" ]; then
                    sudo cp $0 /etc/network/if-up.d/
                else
                    echo "No file copied . User performing MANUALLY"
                fi
	    else
		    echo "sym-link /etc/network/if-up.d/reverse_ssh_tunnel already exists. SKIPPING"
	    fi
        else
            echo "WARNING: Can not find your network manager. Please process the hooks MANUALLY"
        fi
    fi

    ### check if all client dependancies are installed
    echo "Checking all required binaries are installed..."
    DEPENDS=( autossh sshd fail2ban-server )
    process_depends $DEPENDS

    ### Checking if ssh-keygen has been run previously
    if [ -e "$HOME/.ssh/id_rsa.pub" ]; then
        echo "Existing public ssh key found. Please make sure the central server has this key in '$HOME/.ssh/authorized_keys'"
        cat $HOME/.ssh/id_rsa.pub
    else
        if [ "$assume" != "y" ]; then 
            echo -n "No existing keys found for this user. Would you like to run ssh-keygen <y/n> "
            read opt
        fi
        if [ "$opt" = "y" ] || [ "$assume" = "y" ]; then
            ssh-keygen
            echo "Please make sure the central server has this key in '$HOME/.ssh/authorized_keys'"
            cat $HOME/.ssh/id_rsa.pub
        fi
    fi
    ### Add host to the $config_file
    grep $(hostname -s) $config_file
    if [ $? -ne "0" ]; then
        if [ "$assume" != "y" ]; then 
            echo -n "Would you like to add the node to $config_file <y/n> "
            read opt
        fi
        if [ "$opt" = "y" ] || [ "$assume" = "y" ]; then
            echo "What port will be used for the reverse ssh connection? "
            read port
            echo "Adding NODE to $config_file"
            echo "$(hostname -s);$port;$USER;00:00:00:00:00:00" >> $config_file
        fi
    else
        echo "Hostname already found in $config_file . SKIPPING"
    fi
## Import the central server public_key to the current user authorized_keys


## email public key to central server admin
    if [ "$email" = "y" ]; then 
        email_file=$(mktemp)
        echo "public_key" >> $email_file
        cat ~/.ssh/id_rsa.pub >> $email_file
        echo -e "\n entry for reverse_ssh.conf" >> $email_file
        grep $(hostname -s) /etc/reverse_ssh.conf >> $email_file
        mailx -s "new reverse ssh host $(hostname -s)" "$email_address" < $email_file
        rm $email_file
    fi
    echo "INSTALLATION COMPLETE - Please review the messages for any manual steps you need to perform"
    echo "To START. re-run this script without the \"-i\" switch"
    exit 0
fi

process_depends $DEPENDS
##############################
# Read in the config file to arrays (1 for each host/line)
# Check the hostname is expected and which port it creates.
##############################
index="0"
host_found="0"
while read line; do 
        host[$index]="$line"
	if [ "$(hostname -s)" = $(echo "${host[$index]}" | awk -F";" '{print $1}') ]; then
		host_found="1";
		PORT_MIDDLEMAN_WILL_LISTEN_ON=$(echo "${host[$index]}" | awk -F";" '{print $2}')
		SU_USER=$(echo "${host[$index]}" | awk -F";" '{print $3}')
	fi
        index=$(( $index+1 ))
done < $config_file

if [ $host_found -eq "0" ]; then
    	echo "Hostname not found in config. Please correct. Add the hostname to /etc/hosts"
	exit 1
fi

##############################
# Kill any old instances of autossh
##############################
for i in $(ps aux | grep -i "autossh" | grep -v grep | awk '{print $2}')
do
    echo "Killing autossh sessions with PID $i"
    kill -9 $i
done

su -c "autossh -f -N -M $AUTOSSH_PORT -R *:${PORT_MIDDLEMAN_WILL_LISTEN_ON}:localhost:22 ${MIDDLEMAN_SERVER_AND_USERNAME} -oLogLevel=error  -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no" $SU_USER

exit 0
